#define BLINKER_WIFI
#define BLINKER_DUEROS_LIGHT
#define BLINKER_PRINT Serial
#define _TASK_SLEEP_ON_IDLE_RUN

#include <Servo.h>
#include <Blinker.h>
#include <FS.h>  
#include <Ticker.h>

char auth[] = "xxx";
char ssid[] = "xxx";
char pswd[] = "xxx";

String configFile = "/config.txt";       


Servo myservo;
int openDeg = 70;
int closeDeg = 120;
int minDeg =  min(openDeg, closeDeg) + ceil(abs(openDeg - closeDeg)) / 2;


//========== 定时休眠 =========
Ticker timeTicker;
bool isGoingSleep = false;
void checkTime(){
    // 检查当前时间是否需要睡眠
    // 运行时间 23:30-01:00  1小时30分
    BLINKER_LOG("睡眠时间检查");
    int8_t min = Blinker.minute();
    int8_t hour = Blinker.hour();

    int nowMin = hour * 60 + min;
    int openStart = 23*60 + 30;
    int openEnd = 120;
    if (nowMin > openEnd && nowMin < openStart){
        //处于关机时段，判断需要休眠多久
        int cha = openStart - nowMin;
        if (cha > 120) {
            cha = 120;
        }
        BLINKER_LOG("距离开机还有多少分钟", cha);
        ESP.deepSleepInstant(cha * 60 * 1000000, WAKE_RF_DEFAULT);
        isGoingSleep = true;
    }else{
        BLINKER_LOG("处于开机时段");
    }
 
}

void beginTimeTicker(){
    checkTime();
    timeTicker.attach_ms(1800 * 1000, checkTime); //30分钟查询一次时间
}

void checkIsGoingSleep(){
    if(isGoingSleep){
        BLINKER_LOG("休眠不成功");
        checkTime();
    }
}

//=============  led flash ==================
Ticker flashTicker;
bool flashFlag = false;

void closeLed(){
    digitalWrite(LED_BUILTIN, HIGH);
}

void openLed(){
    digitalWrite(LED_BUILTIN, LOW);
}

void flashLed(){
    if(flashFlag){
        closeLed();
    }else{
        openLed();
    }
    flashFlag = !flashFlag;
    if (Blinker.init())
    {
        flashTicker.detach();
        closeLed();
       // beginTimeTicker();
    }
}

void beginFlash(){
    flashTicker.attach_ms(500, flashLed);
}
void stopFlash(){
    flashTicker.detach();
}



//========= led开关  =========
BlinkerButton LedBtn("led_btn");

void LedBtn_Callback(const String & state) {
    BLINKER_LOG("get button state: ", state);
    if (state=="on") {
        openLed();
        LedBtn.print("on");
    } else if(state=="off"){
        closeLed();
        LedBtn.print("off");
    }
}


// =============== 房间灯控制 ============
Ticker minTicker;
Ticker closePwmTicker;

BlinkerButton LightBtn("light_btn");

void initServo(){
    myservo.attach(D5, 500, 2500); 
}

void closePwm(){

   
   // myservo.detach();

    BLINKER_LOG("closePwm");
    closePwmTicker.detach();
    // pinMode(D5, INPUT);

}

void gotoMinDeg(){
    // delay(2000); 定时器里调用delay会出错。这个定时器是callback函数里面开启的，如果是在setup里面开的定时器又不会出错。
    myservo.write(minDeg); 
   // closePwmTicker.attach_ms(2000, closePwm);
   // myservo.detach();
    minTicker.detach();

}

bool doOpenLight = false;
void LightBtn_Callback(const String & state) {
    if(doOpenLight){
        BLINKER_LOG("is doing");
        return;
    }
    doOpenLight = true;
    BLINKER_LOG("get button state: ", state);
    initServo();
    if (state=="on") {
        LightBtn.print("on");
        myservo.write(openDeg);  
    } else if(state=="off"){
        LightBtn.print("off");
        myservo.write(closeDeg);   
    }


    Blinker.delay(1500);

    myservo.write(minDeg); 

    Blinker.delay(1500);

    myservo.detach();

    Blinker.delay(500);

    pinMode(D5, INPUT);
    BLINKER_LOG("closePwm");
    doOpenLight = false;
   // minTicker.attach_ms(1500, gotoMinDeg);
   
}

void duerPowerState(const String & state)
{
    BLINKER_LOG("duerPowerState: ", state);
    LightBtn_Callback(state);
}


// =============== 舵机方向控制 ============
BlinkerSlider FxSlide("fx_slide");

void FxSlide_Callback(int32_t value)
{
    initServo();
    myservo.write(value);   
    //closePwmTicker.attach_ms(2000, closePwm);
}


// =============== 舵机config设置 ============

void setOnDeg(const String & data){
    int index = data.indexOf(',');
    String begin = data.substring(0, index);
    BLINKER_LOG("set openDeg:", begin);
    openDeg = begin.toInt();

    String end = data.substring(index + 1);
    closeDeg = end.toInt();
    BLINKER_LOG("set closeDeg:", end);

    minDeg =  min(openDeg, closeDeg) + ceil(abs(openDeg - closeDeg)) / 2;
}

void initConfig(){

    if(SPIFFS.begin()){ // 启动SPIFFS
        Serial.println("SPIFFS Started.");
    } else {
        Serial.println("SPIFFS Failed to Start.");
    }

    //确认闪存中是否有file_name文件
    if (SPIFFS.exists(configFile)){
        File dataFile = SPIFFS.open(configFile, "r"); 
        String str = dataFile.readString();
        BLINKER_LOG("get config str:", str);
        dataFile.close();   

        setOnDeg(str);   
    }
} 

void dataRead(const String & data)
{
    BLINKER_LOG("Blinker readString: ", data);
    File dataFile = SPIFFS.open(configFile, "w");
    dataFile.print(data);     
    dataFile.close();
    setOnDeg(data);
}


void setup() {
    // 初始化串口
    Serial.begin(115200);
    BLINKER_DEBUG.stream(BLINKER_PRINT); 

    pinMode(LED_BUILTIN, OUTPUT);
    closeLed();

    beginFlash();
    Blinker.begin(auth, ssid, pswd);

    BLINKER_LOG("device bgein end");

    initConfig();

    LedBtn.attach(LedBtn_Callback);
    LightBtn.attach(LightBtn_Callback);

    FxSlide.attach(FxSlide_Callback);

    Blinker.attachData(dataRead);
    BlinkerDuerOS.attachPowerState(duerPowerState);

    wifi_set_sleep_type(LIGHT_SLEEP_T);
}

void loop() {
    Blinker.run();
    wifi_set_sleep_type(LIGHT_SLEEP_T);
    // checkIsGoingSleep();
}
